package com.ctshk.rpc.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ctshk.common.dto.Result;
import com.ctshk.common.enums.CompanyType;
import com.ctshk.common.enums.IsDeletedCode;
import com.ctshk.common.enums.SystemBusinessType;
import com.ctshk.common.enums.SystemError;
import com.ctshk.common.exception.BusinessException;
import com.ctshk.common.mail.core.MailTemplate;
import com.ctshk.common.model.PageResponse;
import com.ctshk.common.utils.EntityUtil;
import com.ctshk.common.utils.SnowflakeIdWorker;
import com.ctshk.common.utils.ValidatorUtil;
import com.ctshk.rpc.system.dto.DispatchOrderRulePageDTO;
import com.ctshk.rpc.system.dto.DispatchOrderUserListDTO;
import com.ctshk.rpc.system.dto.UserDTO;
import com.ctshk.rpc.system.entity.DispatchOrderLog;
import com.ctshk.rpc.system.entity.DispatchOrderRule;
import com.ctshk.rpc.system.entity.DispatchOrderUser;
import com.ctshk.rpc.system.mapper.DispatchOrderLogMapper;
import com.ctshk.rpc.system.mapper.DispatchOrderRuleMapper;
import com.ctshk.rpc.system.mapper.DispatchOrderUserMapper;
import com.ctshk.rpc.system.req.DispatchOrderRuleGetUserReq;
import com.ctshk.rpc.system.req.DispatchOrderRulePageReq;
import com.ctshk.rpc.system.req.DispatchOrderRuleSaveReq;
import com.ctshk.rpc.system.service.IDispatchOrderRuleService;
import com.ctshk.rpc.system.service.ISysUserService;
import com.github.houbb.heaven.util.util.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 谢诗宏
 * @since 2021-05-24
 */
@Slf4j
@DubboService
public class DispatchOrderRuleServiceImpl extends ServiceImpl<DispatchOrderRuleMapper, DispatchOrderRule> implements IDispatchOrderRuleService {

    @Autowired
    private DispatchOrderRuleMapper dispatchOrderRuleMapper;

    @Autowired
    private DispatchOrderUserMapper dispatchOrderUserMapper;

    @Autowired
    private DispatchOrderLogMapper dispatchOrderLogMapper;

    @DubboReference
    ISysUserService sysUserService;

    @Autowired
    MailTemplate mailTemplate;

    private static final Long SYSTEM_USER_ID = 1L;

    @Override
    public Result<PageResponse<DispatchOrderRulePageDTO>> page(DispatchOrderRulePageReq req) {
        Page<DispatchOrderRule> page = new Page<>(req.getPageNo(), req.getPageSize());
        IPage<DispatchOrderRule> iPage = dispatchOrderRuleMapper.selectPage(page, new QueryWrapper<DispatchOrderRule>().lambda()
                .eq(DispatchOrderRule::getIsDeleted, IsDeletedCode.NO.getCode())
                .orderByDesc(DispatchOrderRule::getGmtCreate)
                .select(DispatchOrderRule::getId, DispatchOrderRule::getSystemCode, DispatchOrderRule::getName, DispatchOrderRule::getCompanyType,
                        DispatchOrderRule::getBusinessTypeId, DispatchOrderRule::getBusinessTypeName, DispatchOrderRule::getCount,
                        DispatchOrderRule::getPersonCount, DispatchOrderRule::getCreateId, DispatchOrderRule::getPushSms,
                        DispatchOrderRule::getPushEmail, DispatchOrderRule::getPushMsg));
        List<DispatchOrderRule> records = iPage.getRecords();
        if (CollectionUtil.isEmpty(records)) {
            return Result.success(new PageResponse<DispatchOrderRulePageDTO>(new ArrayList<>(), iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize()));
        }
        List<DispatchOrderRulePageDTO> list = EntityUtil.copyList(iPage.getRecords(), DispatchOrderRulePageDTO.class);
        Set<Long> userIds = records.stream().map(DispatchOrderRule::getCreateId).collect(Collectors.toSet());
        List<UserDTO> userDTOS = sysUserService.queryCacheUsers(userIds);
        list.forEach(record -> {
            for (UserDTO userDTO : userDTOS) {
                if (userDTOS != null && Objects.equals(userDTO.getId(), record.getCreateId())) {
                    record.setCreateDept(userDTO.getCreateDept());
                    break;
                }
            }
            record.setCompanyTypeName(CompanyType.getCompanyTypeName(record.getCompanyType()));
        });
        return Result.success(new PageResponse<DispatchOrderRulePageDTO>(list, iPage.getCurrent() == 1, iPage.getTotal() <= (iPage.getCurrent() * iPage.getSize()), iPage.getTotal(), iPage.getCurrent(), iPage.getSize()));
    }

    @Override
    public Result save(DispatchOrderRuleSaveReq req, Long userId) {
        DispatchOrderRule dispatchOrderRuleD = baseMapper.selectOne(new QueryWrapper<DispatchOrderRule>().lambda()
                .eq(DispatchOrderRule::getBusinessTypeId, req.getBusinessTypeId())
                .eq(DispatchOrderRule::getCompanyType, req.getCompanyType())
                .eq(DispatchOrderRule::getIsDeleted, IsDeletedCode.NO.getCode()));
        DispatchOrderRule dispatchOrderRule = EntityUtil.copy(req, DispatchOrderRule.class);
        dispatchOrderRule.setName(req.getName());
        dispatchOrderRule.setBusinessTypeId(req.getBusinessTypeId());
        dispatchOrderRule.setBusinessTypeName(SystemBusinessType.parseValue(req.getBusinessTypeId()));
        dispatchOrderRule.setCompanyType(req.getCompanyType());
        List<Long> userIdList = req.getUserIdList();
        // 计算分配人数
        Integer personCount = userIdList.size();
        dispatchOrderRule.setPersonCount(personCount);
        LocalDateTime now = LocalDateTime.now();
        if (req.getId() == null) { // 新增派单规则
            if (null != dispatchOrderRuleD) {
                throw new BusinessException(SystemError.SYS_432, req.getName());
            }
            dispatchOrderRule.setId(SnowflakeIdWorker.nextId());
            // 设置默认分配人
            dispatchOrderRule.setNextUserId(userIdList.get(0));
            dispatchOrderRule.setCount(0L);
            dispatchOrderRule.setCreateId(userId);
            dispatchOrderRule.setGmtCreate(now);
            dispatchOrderRule.setModifiedId(userId);
            dispatchOrderRule.setGmtModified(now);
            dispatchOrderRule.setIsDeleted(IsDeletedCode.NO.getCode());
            dispatchOrderRuleMapper.insert(dispatchOrderRule);
        } else { // 更新派单规则
            if (null == dispatchOrderRuleD) {
                throw new BusinessException(SystemError.SYS_411);
            }
            Long nextUserId = null;
            // 判断原计划下个分配人员，是否已经不在分配人员中
            if (!userIdList.contains(dispatchOrderRuleD.getNextUserId())) {
                nextUserId = userIdList.get(0);
            }
            dispatchOrderRuleMapper.update(null, new UpdateWrapper<DispatchOrderRule>().lambda()
                    .eq(DispatchOrderRule::getId, req.getId())
                    .set(DispatchOrderRule::getBusinessTypeId, req.getBusinessTypeId())
                    .set(DispatchOrderRule::getCompanyType, req.getCompanyType())
                    .set(DispatchOrderRule::getPushSms, req.getPushSms())
                    .set(DispatchOrderRule::getPushEmail, req.getPushEmail())
                    .set(DispatchOrderRule::getPushMsg, req.getPushMsg())
                    .set(DispatchOrderRule::getCount, 0L)
                    .set(DispatchOrderRule::getPersonCount, personCount)
                    .set(nextUserId != null, DispatchOrderRule::getNextUserId, nextUserId)
                    .set(DispatchOrderRule::getModifiedId, userId)
                    .set(DispatchOrderRule::getGmtModified, now));
            dispatchOrderUserMapper.delete(new QueryWrapper<DispatchOrderUser>().lambda()
                    .eq(DispatchOrderUser::getDispatchId, req.getId()));
        }
        List<DispatchOrderUser> dispatchOrderUserList = new ArrayList<>();
        HashSet<Long> longs = new HashSet<>(userIdList);
        List<UserDTO> userDTOS = sysUserService.queryCacheUsers(longs);
        for (int i = 0; i < userIdList.size(); i++) {
            UserDTO userDTO = userDTOS.get(i);
            DispatchOrderUser dispatchOrderUser = new DispatchOrderUser();
            dispatchOrderUser.setId(SnowflakeIdWorker.nextId());
            dispatchOrderUser.setDispatchId(dispatchOrderRule.getId());
            dispatchOrderUser.setDispatchUserId(userIdList.get(i));
            dispatchOrderUser.setDispatchUserName(userDTO.getFullName());
            dispatchOrderUser.setSort(i + 1);
            dispatchOrderUser.setCreateId(userId);
            dispatchOrderUser.setGmtModified(now);
            dispatchOrderUser.setModifiedId(userId);
            dispatchOrderUser.setGmtModified(now);
            dispatchOrderUser.setIsDeleted(IsDeletedCode.NO.getCode());
            dispatchOrderUserList.add(dispatchOrderUser);
        }
        dispatchOrderUserMapper.insertBatchSomeColumn(dispatchOrderUserList);
        return Result.success(dispatchOrderRule.getId());
    }

    @Override
    public Result getDispatchUserId(DispatchOrderRuleGetUserReq req) {
        log.info("【派单系统-获取派单用户ID】方法入参:{}", req);
        ValidatorUtil.validate(req);
        DispatchOrderRule dispatchOrderRule = dispatchOrderRuleMapper.selectOne(new QueryWrapper<DispatchOrderRule>().lambda()
                .eq(DispatchOrderRule::getBusinessTypeId, req.getBusinessTypeId())
                .eq(DispatchOrderRule::getCompanyType, req.getCompanyType())
                .eq(DispatchOrderRule::getIsDeleted, IsDeletedCode.NO.getCode()));
        if (null == dispatchOrderRule) {
            log.error("【派单系统-获取派单用户ID】该公司类型和业务类型没有匹配的派单规则");
            return Result.failed(SystemError.SYS_411, req);
        }

        List<DispatchOrderUser> dispatchOrderUserList = dispatchOrderUserMapper.selectList(new QueryWrapper<DispatchOrderUser>().lambda()
                .eq(DispatchOrderUser::getDispatchId, dispatchOrderRule.getId())
                .orderByAsc(DispatchOrderUser::getSort));
        // 计算下个用户ID
        Long dispatchUserId = null;
        for (int i = 0; i < dispatchOrderUserList.size(); i++) {
            DispatchOrderUser dispatchOrderUser = dispatchOrderUserList.get(i);
            if (Objects.equals(dispatchOrderRule.getNextUserId(), dispatchOrderUser.getDispatchUserId())) {
                if (Objects.equals(dispatchOrderUser.getSort(), dispatchOrderUserList.size())) {
                    dispatchUserId = dispatchOrderUserList.get(0).getDispatchUserId();
                } else {
                    dispatchUserId = dispatchOrderUserList.get(i + 1).getDispatchUserId();
                }
            }
        }
        // 次数+1
        long count = dispatchOrderRule.getCount() + 1;
        LocalDateTime now = LocalDateTime.now();
        dispatchOrderRuleMapper.update(null, new UpdateWrapper<DispatchOrderRule>().lambda()
                .eq(DispatchOrderRule::getId, dispatchOrderRule.getId())
                .set(DispatchOrderRule::getCount, count)
                .set(DispatchOrderRule::getNextUserId, dispatchUserId)
                .set(DispatchOrderRule::getModifiedId, dispatchUserId)
                .set(DispatchOrderRule::getGmtModified, now));
        /**
         * 记录推送日志
         */
        DispatchOrderLog dispatchOrderLog = new DispatchOrderLog();
        dispatchOrderLog.setId(SnowflakeIdWorker.nextId());
        dispatchOrderLog.setDispatchId(dispatchOrderRule.getId());
        dispatchOrderLog.setDispatchUserId(dispatchOrderRule.getNextUserId());
//        dispatchOrderLog.setOrderNumber(req.getOrderNumber());
        dispatchOrderLog.setCreateId(dispatchUserId);
        dispatchOrderLog.setGmtCreate(now);
        dispatchOrderLog.setModifiedId(dispatchUserId);
        dispatchOrderLog.setGmtModified(now);
        dispatchOrderLog.setIsDeleted(IsDeletedCode.NO.getCode());
        dispatchOrderLogMapper.insert(dispatchOrderLog);
        /**
         * 推送记录
         */
        if (Objects.equals(dispatchOrderRule.getPushSms(), 1)) { // 推送短信
//            SmsUtil.sendSms();
        }
        if (Objects.equals(dispatchOrderRule.getPushEmail(), 1)) { // 推送邮件
//            mailTemplate.sendSingleImgMail();
        }
        if (Objects.equals(dispatchOrderRule.getPushMsg(), 1)) { // 推送站内消息

        }
        return Result.success(dispatchOrderRule.getNextUserId());
    }

    @Override
    public Result<List<DispatchOrderUserListDTO>> getDispatchUserListById(Long id) {
        DispatchOrderRule dispatchOrderRule = dispatchOrderRuleMapper.selectOne(new QueryWrapper<DispatchOrderRule>().lambda()
                .eq(DispatchOrderRule::getId, id)
                .eq(DispatchOrderRule::getIsDeleted, IsDeletedCode.NO.getCode()));
        if (null == dispatchOrderRule) {
            log.error("【派单系统-根据派单规则ID获取派单用户列表】派单ID不存在");
            return Result.failed(SystemError.SYS_411);
        }
        List<DispatchOrderUser> dispatchOrderUserList = dispatchOrderUserMapper.selectList(new QueryWrapper<DispatchOrderUser>().lambda()
                .eq(DispatchOrderUser::getDispatchId, id)
                .eq(DispatchOrderUser::getIsDeleted, IsDeletedCode.NO.getCode()));
        List<DispatchOrderUserListDTO> list = EntityUtil.copyList(dispatchOrderUserList, DispatchOrderUserListDTO.class);
        Set<Long> userIds = list.stream().map(DispatchOrderUserListDTO::getDispatchUserId).collect(Collectors.toSet());
        List<UserDTO> userDTOS = sysUserService.queryCacheUsers(userIds);
        list.forEach(record -> {
            for (UserDTO userDTO : userDTOS) {
                if (Objects.equals(userDTO.getId(), record.getDispatchUserId())) {
                    record.setDispatchUserNameDept(userDTO.getCreateDept());
                    break;
                }
            }
        });
        return Result.success(list);
    }
}
